package wkt.question;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import net.xnzn.framework.data.mybatis.Paging;
import net.xnzn.framework.id.Id;
import net.xnzn.framework.secure.filter.annotation.RequiresAuthentication;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import wkt.RequireStudentLogin;
import wkt.WebUtils;
import wkt.exam.ExamRecord;
import wkt.exam.ExamRecordMapper;
import wkt.exam.ExamWrongQuestion;
import wkt.exam.ExamWrongQuestionMapper;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/question")
@Validated
public class QuestionController {
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private AnswerMapper answerMapper;
    @Autowired
    private ExamRecordMapper examRecordMapper;
    @Autowired
    private ExamWrongQuestionMapper examWrongQuestionMapper;

    public static void main(String[] args) {
        String str = "<p><img src=\"https://wangkaotong-file.oss-cn-shanghai.aliyuncs.com/question/276641840764030976.png\" alt=\"\" width=\"499\" height=\"146\">kkkk<img src=\"https://wangkaotong-file.oss-cn-shanghai.aliyuncs.com/question/276631574294827008.jpg\" alt=\"\" width=\"75\" height=\"113\"></p>";
        System.out.println(str.replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\" style='max-width:100%;'>"));
        System.out.println(str.replaceAll("(<img\\s.*\\s)width=\".*\"\\sheight=\".*\">", "$1 style='max-width:50px;max-height:30px;'>"));
    }

    @PostMapping("/list/{pageSize}/{pageNum}")
    @RequiresAuthentication
    public Paging<Question> list(@RequestBody Question question, @PathVariable @Range(min = 1, max = 100, message = "请输入1-100") int pageSize, @PathVariable int pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        final List<Question> questions = questionMapper.selectList(Wrappers.lambdaQuery(Question.class)
                .select(Question::getId, Question::getBasicCode, Question::getQuestion, Question::getType, Question::getAnalyzes)
                .eq(Question::getBasicCode, question.getBasicCode())
                .eq(Question::getType, question.getType())
                .eq(Question::getState, "NORMAL")
                .orderByDesc(Question::getId));
        if (CollUtil.isEmpty(questions)) return Paging.build(questions);

        final List<Answer> answers = answerMapper.selectList(Wrappers.lambdaQuery(Answer.class)
                .select(Answer::getId, Answer::getQuestionId, Answer::getAnswer, Answer::isRights)
                .eq(Answer::getState, "NORMAL")
                .orderByAsc(Answer::getId)
                .in(Answer::getQuestionId, questions.stream().map(Question::getId).collect(Collectors.toSet())));
        final Map<Long, List<Answer>> questionId_answers = answers.stream().collect(Collectors.groupingBy(Answer::getQuestionId, Collectors.mapping(answer -> {
            answer.setAnswer(answer.getAnswer().replaceFirst("<p>(.*?)</p>", "$1").replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\" style='max-width:50px;max-height:30px;'>"));
            return answer;
        }, Collectors.toList())));

        questions.forEach(question1 -> {
            if (CharSequenceUtil.isNotBlank(question1.getQuestion())) {
                question1.setQuestion(question1.getQuestion().replaceFirst("<p>(.*?)</p>", "$1").replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\" style='max-width:50px;max-height:30px;'>"));
            }
            if (CharSequenceUtil.isNotBlank(question1.getAnalyzes())) {
                question1.setAnalyzes(question1.getAnalyzes().replaceFirst("<p>(.*?)</p>", "$1").replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\" style='max-width:50px;max-height:30px;'>"));
            }
            question1.setAnswers(questionId_answers.get(question1.getId()));
        });
        return Paging.build(questions);
    }

    @PostMapping("/list-for-show/{pageSize}/{pageNum}")
    @RequireStudentLogin
    public Paging<Question> listForShow(@RequestBody Question question, @PathVariable @Range(min = 1, max = 100, message = "请输入1-100") int pageSize, @PathVariable int pageNum) {
        List<Question> questions;
        if (!question.isFromWrongBook()) {
            //清除历史答题进度
            if (question.isClearPreviousAnswerProcess()) {
                examRecordMapper.update(null, Wrappers.lambdaUpdate(ExamRecord.class)
                        .eq(ExamRecord::getStudentId, WebUtils.studentId())
                        .eq(ExamRecord::getBasicCode, question.getBasicCode())
                        .eq(ExamRecord::getType, question.getType())
                        .eq(ExamRecord::getState, "NORMAL")
                        .set(ExamRecord::getState, "DELETE"));
            }

            //从题库获取题目
            PageHelper.startPage(pageNum, pageSize);
            questions = questionMapper.listUntrainedQuestion(question.getBasicCode(), question.getType(), WebUtils.studentId());
        } else {
            //从错题本获取题目
            PageHelper.startPage(pageNum, pageSize);
            questions = examWrongQuestionMapper.listUntrainedQuestion(question.getBasicCode(), question.getType(), WebUtils.studentId(), question.getSeqId());
        }

        if (CollUtil.isEmpty(questions)) return Paging.build(questions);

        //批量获取答案
        final Set<Long> questionIds = questions.stream().map(Question::getId).collect(Collectors.toSet());
        final List<Answer> answers = answerMapper.selectList(Wrappers.lambdaQuery(Answer.class)
                .select(Answer::getId, Answer::getQuestionId, Answer::getAnswer, Answer::isRights)
                .eq(Answer::getState, "NORMAL")
                .orderByAsc(Answer::getId)
                .in(Answer::getQuestionId, questionIds));
        final Map<Long, List<Answer>> questionId_answers = answers.stream().collect(Collectors.groupingBy(Answer::getQuestionId, Collectors.mapping(answer -> {
            answer.setAnswer(answer.getAnswer().replaceFirst("<p>(.*?)</p>", "$1").replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\"  class='answer-image'>"));
            return answer;
        }, Collectors.toList())));

        //获取是否收藏
        final QueryWrapper<ExamWrongQuestion> questionQueryWrapper = new QueryWrapper<>();
        final List<Map<String, Object>> starCounts = examWrongQuestionMapper.selectMaps(questionQueryWrapper.select("question_id,count(1) as count").eq("student_id", WebUtils.studentId()).in("question_id", questionIds).eq("source", "STAR").groupBy("question_id"));
        Map<Long, Boolean> questionId_starCount = Maps.newHashMap();
        if (CollUtil.isNotEmpty(starCounts)) {
            for (Map<String, Object> starCount : starCounts) {
                questionId_starCount.put((Long) starCount.get("question_id"), ((Long) starCount.get("count")) > 0);
            }
        }

        //答题情况
        Map<Long, Map<String, Object>> questionId_count = Maps.newHashMap();
        final QueryWrapper<ExamRecord> examRecordQueryWrapper = new QueryWrapper<>();
        final List<Map<String, Object>> examRecordCounts = examRecordMapper.selectMaps(examRecordQueryWrapper.select("question_id,rights,count(1) as count").eq("student_id", WebUtils.studentId()).in("question_id", questionIds).groupBy("question_id", "rights"));
        if (CollUtil.isNotEmpty(examRecordCounts)) {
            for (Map<String, Object> map : examRecordCounts) {
                final Map<String, Object> counts = questionId_count.getOrDefault((Long) map.get("question_id"), Maps.newHashMap());
                counts.put((Boolean) map.get("rights") ? "rightCount" : "wrongCount", map.get("count"));
                questionId_count.put((Long) map.get("question_id"), counts);
            }
        }

        //填充题目
        questions.forEach(question1 -> {
            if (CharSequenceUtil.isNotBlank(question1.getQuestion())) {
                question1.setQuestion(question1.getQuestion().replaceFirst("<p>(.*?)</p>", "$1").replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\" class='question-image'>"));
            }
            if (CharSequenceUtil.isNotBlank(question1.getAnalyzes())) {
                question1.setAnalyzes(question1.getAnalyzes().replaceFirst("<p>(.*?)</p>", "$1").replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\" class='question-image'>"));
            }
            question1.setAnswers(questionId_answers.get(question1.getId()));
            question1.setStared(questionId_starCount.getOrDefault(question1.getId(), false));

            final Map<String, Object> myAnswerCount = questionId_count.getOrDefault(question1.getId(), Maps.newHashMap());
            question1.setMyRightAnswerCount((Long) myAnswerCount.getOrDefault("rightCount", 0L));
            question1.setMyWrongAnswerCount((Long) myAnswerCount.getOrDefault("wrongCount", 0L));
        });


        return Paging.build(questions);
    }

    @PostMapping("/list-for-show-for-pc/{studentId}/{pageSize}/{pageNum}")
    @RequiresAuthentication
    public Paging<Question> listForShowForPc(@PathVariable Long studentId,@RequestBody Question question, @PathVariable @Range(min = 1, max = 100, message = "请输入1-100") int pageSize, @PathVariable int pageNum) {
        //从错题本获取题目
        PageHelper.startPage(pageNum, pageSize);
        List<Question> questions = examWrongQuestionMapper.listUntrainedQuestion(question.getBasicCode(), question.getType(), studentId, question.getSeqId());

        if (CollUtil.isEmpty(questions)) return Paging.build(questions);

        //批量获取答案
        final Set<Long> questionIds = questions.stream().map(Question::getId).collect(Collectors.toSet());
        final List<Answer> answers = answerMapper.selectList(Wrappers.lambdaQuery(Answer.class)
                .select(Answer::getId, Answer::getQuestionId, Answer::getAnswer, Answer::isRights)
                .eq(Answer::getState, "NORMAL")
                .orderByAsc(Answer::getId)
                .in(Answer::getQuestionId, questionIds));
        final Map<Long, List<Answer>> questionId_answers = answers.stream().collect(Collectors.groupingBy(Answer::getQuestionId, Collectors.mapping(answer -> {
            answer.setAnswer(answer.getAnswer().replaceFirst("<p>(.*?)</p>", "$1").replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\" style='max-width:50px;max-height:30px;'>"));
            return answer;
        }, Collectors.toList())));

        //获取是否收藏
        final QueryWrapper<ExamWrongQuestion> questionQueryWrapper = new QueryWrapper<>();
        final List<Map<String, Object>> starCounts = examWrongQuestionMapper.selectMaps(questionQueryWrapper.select("question_id,count(1) as count").eq("student_id", studentId).in("question_id", questionIds).eq("source", "STAR").groupBy("question_id"));
        Map<Long, Boolean> questionId_starCount = Maps.newHashMap();
        if (CollUtil.isNotEmpty(starCounts)) {
            for (Map<String, Object> starCount : starCounts) {
                questionId_starCount.put((Long) starCount.get("question_id"), ((Long) starCount.get("count")) > 0);
            }
        }

        //答题情况
        Map<Long, Map<String, Object>> questionId_count = Maps.newHashMap();
        final QueryWrapper<ExamRecord> examRecordQueryWrapper = new QueryWrapper<>();
        final List<Map<String, Object>> examRecordCounts = examRecordMapper.selectMaps(examRecordQueryWrapper.select("question_id,rights,count(1) as count").eq("student_id", studentId).in("question_id", questionIds).groupBy("question_id", "rights"));
        if (CollUtil.isNotEmpty(examRecordCounts)) {
            for (Map<String, Object> map : examRecordCounts) {
                final Map<String, Object> counts = questionId_count.getOrDefault((Long) map.get("question_id"), Maps.newHashMap());
                counts.put((Boolean) map.get("rights") ? "rightCount" : "wrongCount", map.get("count"));
                questionId_count.put((Long) map.get("question_id"), counts);
            }
        }

        //填充题目
        questions.forEach(question1 -> {
            if (CharSequenceUtil.isNotBlank(question1.getQuestion())) {
                question1.setQuestion(question1.getQuestion().replaceFirst("<p>(.*?)</p>", "$1").replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\" style='max-width:50px;max-height:30px;'>"));
            }
            if (CharSequenceUtil.isNotBlank(question1.getAnalyzes())) {
                question1.setAnalyzes(question1.getAnalyzes().replaceFirst("<p>(.*?)</p>", "$1").replaceAll("<img\\s+src\\s*=\\s*\"([^\"]+)[^>]*>", "<img src=\"$1\" style='max-width:50px;max-height:30px;'>"));
            }
            question1.setAnswers(questionId_answers.get(question1.getId()));
            question1.setStared(questionId_starCount.getOrDefault(question1.getId(), false));

            final Map<String, Object> myAnswerCount = questionId_count.getOrDefault(question1.getId(), Maps.newHashMap());
            question1.setMyRightAnswerCount((Long) myAnswerCount.getOrDefault("rightCount", 0L));
            question1.setMyWrongAnswerCount((Long) myAnswerCount.getOrDefault("wrongCount", 0L));
        });


        return Paging.build(questions);
    }

    @PostMapping("/get")
    @RequiresAuthentication
    public Question get(@RequestBody Question question) {
        final Question question1 = questionMapper.selectOne(Wrappers.lambdaQuery(Question.class)
                .select(Question::getId, Question::getBasicCode, Question::getQuestion, Question::getType, Question::getAnalyzes)
                .eq(Question::getId, question.getId()));
        final List<Answer> answers = answerMapper.selectList(Wrappers.lambdaQuery(Answer.class)
                .select(Answer::getId, Answer::getQuestionId, Answer::getAnswer, Answer::isRights)
                .eq(Answer::getState, "NORMAL")
                .orderByAsc(Answer::getId)
                .eq(Answer::getQuestionId, question1.getId()));
        question1.setAnswers(answers);
        return question1;
    }

    @PostMapping("/delete")
    public void delete(@RequestBody Question question) {
        questionMapper.update(null, Wrappers.lambdaUpdate(Question.class)
                .eq(Question::getId, question.getId())
                .set(Question::getState, "DELETE"));
    }

    @PostMapping("/upsert")
    @Transactional(rollbackFor = Exception.class)
    public void update(@RequestBody Question question) {
        if (question.getId() == null) {
            question.setId(Id.next());
            questionMapper.insert(question);
            for (Answer answer : question.getAnswers()) {
                answer.setId(Id.next());
                answer.setQuestionId(question.getId());
                answerMapper.insert(answer);
            }
            return;
        }
        questionMapper.update(null, Wrappers.lambdaUpdate(Question.class)
                .eq(Question::getId, question.getId())
                .set(Question::getQuestion, question.getQuestion())
                .set(Question::getAnalyzes, question.getAnalyzes())
        );
        for (Answer answer : question.getAnswers()) {
            if (answer.getId() == null) {
                answer.setId(Id.next());
                answer.setQuestionId(question.getId());
                answerMapper.insert(answer);
                continue;
            }
            answerMapper.update(null, Wrappers.lambdaUpdate(Answer.class)
                    .eq(Answer::getId, answer.getId())
                    .set(Answer::getAnswer, answer.getAnswer())
                    .set(Answer::isRights, answer.isRights())
            );
        }
        answerMapper.update(null, Wrappers.lambdaUpdate(Answer.class)
                .eq(Answer::getQuestionId, question.getId())
                .notIn(Answer::getId, question.getAnswers().stream().map(Answer::getId).collect(Collectors.toList()))
                .set(Answer::getState, "DELETE")
        );
    }
}
